MySQL 知识卡片(简历版)
这份卡片按你当前简历的项目强度整理。
目标不是 DBA 级全覆盖,而是:
- 能撑住
黑马点评的数据库一致性与高并发追问 - 能撑住
苍穹外卖 AI 智能客服 Agent里的条件更新、唯一约束、事务边界追问 - 能过常规后端一面 / 二面的 MySQL 主干题
1. 存储引擎
- 线上主流默认答
InnoDB InnoDB:支持事务、行锁、MVCC、外键、崩溃恢复MyISAM:不支持事务、不支持行锁、不支持崩溃恢复- 为什么线上基本选
InnoDB - 要事务
- 要并发
- 要 crash-safe
- 要 MVCC
2. 索引
- 索引快的核心不是“排序”,而是
B+ 树降低磁盘 IO - B+ 树更适合数据库的原因
- 非叶子节点只存 key,树更矮
- 查询路径更稳定
- 叶子节点链表化,范围查询更友好
- 红黑树不行:树太高,磁盘 IO 多
- 哈希表不行:不支持范围查询
- 主键索引 = 聚簇索引,叶子节点存整行数据
- 二级索引 = 辅助索引,叶子节点存主键值
- 回表:二级索引查到主键后,再回主键索引查整行
- 覆盖索引:查询字段都在索引里,省掉回表
3. 联合索引
- 联合索引
(a,b,c)本质是按(a,b,c)这个复合键排序 - 排序规则:
- 先按
a a相同再按ba,b都相同再按c- 最左前缀本质:
a全局有序b只有在a确定后局部有序c只有在a,b都确定后局部有序where a=1 and c=1- 先用
a c再过滤where b=1 and c=1- 一般用不好这个联合索引
where a=1 and b>2 and c=3a能用b能用到范围起点- 到了范围查询,
c很难继续完整利用索引排序能力
4. 索引失效
- 联合索引没走最左匹配
- 索引列上做函数 / 计算
- 隐式类型转换
like '%xx'or一边没索引- 命中数据量太大
- 优化器认为大量回表的随机 IO 成本高于全表扫描顺序 IO
- 记一句:
- 失效不只是不符合规则
- 也可能是优化器算完成本后主动放弃索引
5. EXPLAIN
type看访问方式- 至少要知道:
system > const > eq_ref > ref > range > index > ALL - 一般看到
ALL要警惕全表扫描 key看实际用了哪个索引rows看预计扫描多少行extra常看:Using index:覆盖索引Using where:还要额外过滤Using filesort:额外排序Using temporary:临时表,通常不理想
6. 事务隔离级别
- 四种隔离级别:
- 读未提交
- 读已提交
- 可重复读
- 可串行化
- 读未提交:脏读、不可重复读、幻读都可能发生
- 读已提交:防脏读
- 可重复读:防脏读、防不可重复读
- 可串行化:隔离最强,并发最差
- InnoDB 默认是
RR
7. MVCC
- MVCC 主要解决的是
快照读可见性 - 核心依赖:
undo log- 隐藏字段
Read ViewRC- 每次快照读生成新的
Read View - 防脏读,但可能不可重复读
RR- 第一次快照读生成
Read View - 后续复用
- 所以快照读下可重复读
- 记一句:
MVCC 管可见性
8. 锁
当前读才更容易扯到锁- 常见当前读:
select ... for updateupdatedelete- 行锁:锁具体记录
- 间隙锁:锁区间,重点是
防插入 - 临键锁:记录锁 + 间隙锁
- 意向锁:表级标记锁,方便锁兼容判断
- 记一句:
MVCC 管快照读锁机制管当前读并发控制
9. 幻读边界
- 幻读不能简单全归因于 MVCC 解决
- 快照读场景下,RR 下很多时候“看起来没有幻读”
- 本质是一直在看同一张快照
- 真正要防范围内插入新记录
- 主要靠间隙锁 / 临键锁
10. 三大日志
redo log:物理日志,负责持久性和崩溃恢复undo log:负责回滚和 MVCCbinlog:逻辑日志,负责主从复制和归档恢复- 物理日志:记录数据页怎么改了
- 逻辑日志:记录执行了什么变更操作
- 不能只靠
binlog - 它不负责页级恢复
- 它一般在提交时才写
- 事务中途宕机兜不住
11. 两阶段提交
- 两阶段提交是为了解决
redo log和binlog的一致性问题 - 避免主从不一致
- 流程理解:
redo prepare- 写
binlog redo commit- 没有两阶段提交的后果
redo成功但binlog失败:主库新,从库旧binlog成功但redo失败:主库旧,从库新
12. Spring 事务失效
- 最典型:
this自调用绕过代理 - 其他高频失效场景:
- 非
public方法 - 异常被吞
- checked exception 默认不回滚
- 对象不是 Spring 管理的 Bean
- 数据库引擎不支持事务
- 传播行为配置成非事务模式
- 记一句:
事务依赖代理,回滚依赖异常向外抛出
13. 常见 SQL 细节
count(*)和count(1)基本等价- 都会尽量走最小索引树统计
count(字段)还要判断null- 字段没索引时可能更重
delete是 DML- 可回滚
- 慢
- 自增一般不重置
truncate/drop偏 DDL- 快
- 通常不可回滚
truncate清空数据并重置自增drop删除整张表char固定长度varchar变长varchar更省空间- 但更新变长时代价可能更高
14. 外键
- 互联网项目通常不推荐物理外键
- 原因:
- DML 校验有性能损耗
- 高并发下锁竞争和死锁风险更高
- 分库分表演进困难
- 工程治理和迁移成本高
- 不用物理外键,不代表不要关联字段
- 常见替代方案:
- 逻辑外键 + 业务校验
- 唯一索引 / 非空约束 / 状态机
- 本地事务
- MQ 最终一致性
15. 分页
- 深分页慢的核心原因:
offset很大时,前面大量数据都要先扫描再丢弃- 如果还伴随回表,成本更高
- 常见优化方向:
- 覆盖索引
- 延迟关联
- 子查询先拿 ID,再回表
- 基于游标 / 上次最大 ID 分页
16. 主从复制
binlog是主从复制基础- 主库写
binlog - 从库拉取并重放
- 主从延迟常见原因:
- 从库执行慢
- 大事务
- 锁冲突
- 主库写入太猛
- 读写分离后的坑:
- 从库可能读到旧数据
- 强一致读取场景要回主库或做一致性策略
17. 分库分表
- 什么时候考虑:
- 单表数据量太大
- 单库连接 / IO / 存储扛不住
- 写入压力太高
- 分表主要解决:
- 单表过大
- 索引过大
- 单表查询变慢
- 分库主要解决:
- 单机资源瓶颈
- 连接数瓶颈
- 写入吞吐瓶颈
- 常见副作用:
- 跨库事务复杂
- 跨库 join 困难
- 全局 ID、分页、排序都更复杂
18. 结合你项目必须会落的 MySQL 口径
黑马点评- 索引、事务、Lua 预扣后的 MySQL 落库兜底
where stock > 0的条件更新- 唯一约束怎么防一人一单 / 重复回调
- 事务为什么不能
this调 - 为什么锁要包在事务外层
苍穹外卖 AI 智能客服 Agent- 条件更新为什么能保证原子写
- 唯一约束怎么做支付回调幂等
- Redis 持久化状态和数据库真实状态怎么兜底
- 高风险步骤怎么做事务边界和最终确认
19. 当前完成标准
- 如果目标是常规后端一面 / 二面
- 补齐上面 1 到 17,基本算 MySQL 主干完成
- 如果目标是项目深挖
- 还要继续补:
- 慢 SQL 排查
- 死锁定位
- 主从延迟治理
- 分库分表后的事务与分页问题